#pragma once
#include "net.hpp"
#include "message.hpp"

namespace bitrpc
{
    class Callback
    {
    public:
        using ptr = std::shared_ptr<Callback>;
        virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) = 0;
    };

    template <typename T>
    class CallbackT : public Callback
    { /* 这里的T由registerHandler<T>决定 */
    public:
        using ptr = std::shared_ptr<CallbackT<T>>;
        using MessageCallback = std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T> &msg)>;
        /* 这里的MessageCallback时提供给上层注册的cb类型 ，T的类型是RpcResponse/TopicResponse... */
        CallbackT(const MessageCallback &handler) : _handler(handler) {}
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) override
        {
            auto type_msg = std::dynamic_pointer_cast<T>(msg); // 将BaseMessage指针转换成T类型的指针
            DLOG("这是%d的业务功能！",(int)msg->mtype());
            _handler(conn, type_msg);
        }

    private:
        MessageCallback _handler; /* 注意callbackT内部保存的_handler的类型不是T，而是MessageCallback */
    };
    class Dispatcher
    {
    public:
        using ptr = std::shared_ptr<Dispatcher>;
        template <typename T> /* 回调函数的类型是CallbackT<T>::MessageCallback= std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T> &msg)>; */
        void registerHandler(MType mtype, const typename CallbackT<T>::MessageCallback &handler)
        {

            std::unique_lock<std::mutex> lock(_mutex);
            auto cb = std::make_shared<CallbackT<T>>(handler); /* 创建一个CallbackT<T>类型来存储handler，传进来的回调函数 */
            _handlers.insert(std::make_pair(mtype, cb));
        }
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg)
        { /* 这里的msg肯定是BaseMessage类型，是在用户创建接口时指定类型 */
            // 找到消息类型对应的业务处理函数，进行调用即可
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _handlers.find(msg->mtype()); /* 根据msg选择执行的handler */
            if (it != _handlers.end())
            {
                return it->second->onMessage(conn, msg);
            }
            // 没有找到指定类型的处理回调--因为客户端和服务端都是我们自己设计的，因此不可能出现这种情况
            ELOG("收到未知类型的消息: %d！", int(msg->mtype()));
            conn->shutdown();
        }

    private:
        std::mutex _mutex;
        std::unordered_map<MType, Callback::ptr> _handlers; /*  用父类指针来指向CallbackT<T>，利用多态的特性 */
    };
}

/*
     方便用户注册函数,用户注册一个指定类型的回调函数，我们进行封装
     1.有Dispatcher template<typename T>的原因是，想要对于用户进行注册的时候可以注册onmessage的第二个参数
     不为BaseMessage* ptr而为对应的功能模块的指针，这样可以更方便调用每个功能模块的功能(虽然可以在函数内部强转，但是增加用户使用难度)
     2.std::unordered_map<MType, Callback::ptr> _handlers只能存储一个类型的变量，所以创建class callbackT和callback;
     3.回调函数的类型是CallbackT<T>::MessageCallback，Dispatcher的类型是T


     总上来说client还是一样调用dispatcher的onmessage，传的还是(const BaseConnection::ptr &conn, BaseMessage::ptr &msg)
     我们单独加了一层CallbackT模块，用来存储MessageCallback = std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T> &msg)>;
     在利用type调用对应的CallbackT模块时，将msg转换成对应type的msg再去调用CallbackT的onMessage
     此时就解决了上层注册的方法不用是(const BaseConnection::ptr &conn, BaseMessage::ptr &msg)func这种方法

     此时由于hash_map里面不能存储模块类型，所以再添加一层callbackT模块的父类，利用父类指针指向对应的子类对象，调用子类对象的onMessage方法
*/

/*namespace bitrpc
{
    namespace test
    {
        class Callback
        {
        public:
            using ptr = std::shared_ptr<Callback>;
            virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) = 0;
        };

        template <typename T>
        class CallbackT : public Callback
        {
        public:
            using ptr = std::shared_ptr<CallbackT<T>>;
            using Messagecallback = std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T> &ptr)>;
            virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg)
            {
                auto mmsg = std::dynamic_pointer_cast<T>(msg);
                callback(conn,mmsg);
            }
            Messagecallback callback;
        };

        class dispatcher
        {
        public:
            using ptr = std::shared_ptr<dispatcher>;
            template <typename T> 这个T代表的类型 
            void registerfunc(MType mtype, const typename CallbackT<T>::Messagecallback cb)
            {
                auto it = _handlers.find(mtype);
                if (it == _handlers.end())
                {
                    auto cb = std::make_shared<CallbackT<T>>(handler); 创建一个CallbackT<T>类型来存储handler，传进来的回调函数 
                    _handlers.insert(std::make_pair(mtype, cb));
                }
            }

            void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg)
            {
                MType mtype = msg->mtype();
                auto it = _handlers.find(mtype);
                if (it != _handlers.end())
                {
                    it->second->onMessage(conn, msg);
                }
            }

        private:
            std::unordered_map<MType, Callback::ptr> _handlers;
        };
    }

}*/